/**
 * Created by jackliu on 15/12/4.
 */
var CONFIG = require('../../common/config');

var https = require('https');
var crypto = require('crypto');

var cacheManager = require('cache-manager');
var redisStore = require('cache-manager-redis');
var redisCache = cacheManager.caching({
    store: redisStore,
    host: CONFIG.REDIS_SERVER_DOMAIN, // default value
    port: CONFIG.REDIS_SERVER_PORT, // default value
    auth_pass: CONFIG.REDIS_SERVER_PASSWORD, //
    db: CONFIG.REDIS_SERVER_DB_NAME,
    ttl: CONFIG.REDIS_SERVER_TTL
});

//------------------------------------------------------------------
var TokenURL='https://api.weixin.qq.com/cgi-bin/token';
var TicketURL='https://api.weixin.qq.com/cgi-bin/ticket/getticket';
var AppID='wx20927d0e8f52ffff';
var AppSecret='c0038158859fca987d9230daf69c9868';

var TokenKey='_ITB_WECHAT_TOKEN';
var TicketKeyPrefix='_ITB_WECHAT_TICKET_';

// 2小时后过期，需要重新获取数据后计算签名
var ExpireTime = 7000;// 为保险，< 7200

// 随机字符串产生函数
var createNonceStr = function() {
    return Math.random().toString(36).substr(2, 15);
};

// 时间戳产生函数
var createTimeStamp = function () {
    return parseInt(new Date().getTime() / 1000) + '';
};

function sha1(str){
    var md5sum = crypto.createHash("sha1");
    md5sum.update(str);
    str = md5sum.digest("hex");
    return str;
}
// 计算签名
var calcSignature = function (ticket, noncestr, ts, url) {
    var str = 'jsapi_ticket=' + ticket + '&noncestr=' + noncestr + '&timestamp='+ ts +'&url=' + url;
    return sha1(str);
}

// 获取微信签名所需的access_token
var getToken = function(callback){
    redisCache.get(TokenKey, function(error, result){
        // 从缓存获取
        if (error==null && result){
            var tokenObj = result;
            if(tokenObj && tokenObj.create_time){
                var t = createTimeStamp() - tokenObj.create_time;
                if(t < ExpireTime){
                    console.log('WECHAT[getToken] from Cache');
                    return callback(null, tokenObj.access_token);
                }
            }
        }

        // 重新获取
        https.get(TokenURL+ '?grant_type=client_credential&appid='+ AppID +'&secret=' + AppSecret, function(_res) {
            var str = '';
            _res.on('data', function(data){
                str += data;
            });
            _res.on('end', function(){
                try{
                    var resp = JSON.parse(str);
                    // 正常: {"access_token":"ACCESS_TOKEN","expires_in":7200}
                    // 错误: {"errcode":40013,"errmsg":"invalid appid"}
                    if (resp.errcode){
                        return callback(resp.errmsg, null);
                    }

                    // 缓存token
                    var tokenInfo = {
                        access_token: resp.access_token,
                        create_time: createTimeStamp()
                    };
                    redisCache.set(TokenKey,tokenInfo);
                    // 返回token
                    console.log('WECHAT[getToken] get New');
                    callback(null, resp.access_token);

                }catch(e){
                    return callback(e, null);
                }
            });
        }).on('error', function(e){
            console.error(e);
            callback(e,null)
        });
    });

}

// 获取微信签名所需的ticket
var getTicket = function (token,callback) {
    var TicketKey = TicketKeyPrefix+token;
    redisCache.get(TicketKey, function(error, result) {
        // 从缓存获取
        if (error == null && result) {
            var ticketObj = result;
            if (ticketObj && ticketObj.create_time) {
                var t = createTimeStamp() - ticketObj.create_time;
                if (t < ExpireTime) {
                    console.log('WECHAT[getTicket] from Cache');
                    return callback(null, ticketObj.ticket);
                }
            }
        }

        // 重新获取
        https.get(TicketURL+ '?access_token='+ token +'&type=jsapi', function(_res){
            var str = '';
            _res.on('data', function(data){
                str += data;
            });
            _res.on('end', function(){
                try{
                    var resp = JSON.parse(str);
                    // 正常: {"errcode":0, "errmsg":"ok", "ticket":"xxxxx", "expires_in":7200}
                    if (Number(resp.errcode) == 0){
                        // 缓存token
                        var ticketInfo = {
                            ticket: resp.ticket,
                            create_time: createTimeStamp()
                        };
                        redisCache.set(TicketKey,ticketInfo);
                        console.log('WECHAT[getTicket] get New');
                        callback(null, resp.ticket);
                    } else {
                        callback(resp.errmsg, null);
                    }
                }catch(e){
                    return callback(e, null);
                }
            });
        }).on('error', function(e){
            console.error(e);
            callback(e, null)
        });
    });
};

// 获取微信签名
exports.getSignature = function(url,callback){

    console.log("WECHAT[getSignature] URL: ", url);
    if (url==null || url.length<=0){
        return callback('Url Empty', null);
    }

    // 如果缓存中已存在签名，则直接返回签名
    redisCache.get(url, function(error, result){

        // 如果缓存中已存在签名，则直接返回签名
        if (error == null && result){
            var signObj = result;
            if(signObj && signObj.timestamp){
                var t = createTimeStamp() - signObj.timestamp;
                // 未过期，并且访问的是同一个地址
                // 判断地址是因为微信分享出去后会额外添加一些参数，地址就变了不符合签名规则，需重新生成签名
                if(t < ExpireTime && signObj.url == url){
                    console.log('WECHAT[getSignature] from Cache: '+ JSON.stringify(signObj));
                    return callback(null, signObj);
                }
            }
        }

        // 重新获取新的签名
        // 获取access_token
        getToken(function(err, tokenRet){
            if (err){
                return callback(err, null);
            }

            // 获取ticket
            getTicket(tokenRet,function(err2,ticketRet){
                if (err2){
                    return callback(err2, null);
                }

                var appid = AppID;
                var ts = createTimeStamp();
                var nonceStr = createNonceStr();
                var ticket = ticketRet;
                var signature = calcSignature(ticket, nonceStr, ts, url);

                var newSign = {
                    nonceStr: nonceStr
                    ,appId: appid
                    ,timestamp: ts
                    ,signature: signature
                    ,url: url
                };

                // 缓存url对应的签名
                redisCache.set(url,newSign);

                console.log("WECHAT[getSignature] New Signature: "+ JSON.stringify(newSign));
                return callback(null, newSign);
            });
        });
    });
}

//-----------------------------------end-------------------------------

